package stone926.mods.more_enchantments.mixins;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.entity.mob.WitchEntity;
import net.minecraft.entity.projectile.thrown.PotionEntity;
import net.minecraft.entity.raid.RaiderEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionUtil;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.interfaces.IWitch;
import stone926.mods.more_enchantments.util.RandomUtil;

import java.util.ArrayList;

@Mixin(WitchEntity.class)
public abstract class WitchEntityMixin extends RaiderEntity implements IWitch {

  private boolean strengthened = false;

  protected WitchEntityMixin(EntityType<? extends RaiderEntity> entityType, World world) {
    super(entityType, world);
  }

  @Override
  public boolean isStrengthened() {
    return strengthened;
  }

  @Override
  public void setStrengthened(boolean strengthened) {
    this.strengthened = strengthened;
  }

  @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/thrown/PotionEntity;setItem(Lnet/minecraft/item/ItemStack;)V"))
  private void setItem(PotionEntity potionEntity, ItemStack stack) {
    if (!isStrengthened()) {
      potionEntity.setItem(stack);
    } else {
      potionEntity.setItem(PotionUtil.setCustomPotionEffects(
        new ItemStack(Items.SPLASH_POTION),
        new ArrayList<>() {{
          RandomUtil.runFunctionsIfPossible(
            MathHelper.nextFloat(random, 0.3F, 0.7F), random,
            () -> add(new StatusEffectInstance(StatusEffects.BAD_OMEN, 60, RandomUtil.nextInt(3, 10, random))),
            () -> add(new StatusEffectInstance(StatusEffects.NAUSEA, RandomUtil.nextInt(5 * 20, 10 * 20, random), 1)),
            () -> add(new StatusEffectInstance(StatusEffects.INSTANT_DAMAGE, 1, RandomUtil.nextInt(1, 4, random))),
            () -> add(new StatusEffectInstance(StatusEffects.SLOWNESS, RandomUtil.nextInt(10 * 20, 60 * 20, random), RandomUtil.nextInt(3, random))),
            () -> add(new StatusEffectInstance(StatusEffects.MINING_FATIGUE, RandomUtil.nextInt(5 * 20, 20 * 20, random), RandomUtil.nextInt(5, random)))
          );
          RandomUtil.runIfPossible(
            MathHelper.nextFloat(random, 0.2F, 0.5F), random,
            () -> add(new StatusEffectInstance(StatusEffects.INSTANT_DAMAGE, 1, RandomUtil.nextInt(3, random)))
          );
          RandomUtil.runIfPossible(
            MathHelper.nextFloat(random, 0.3F, 0.4F), random,
            () -> random.nextBoolean() ?
              add(new StatusEffectInstance(MoreEnchantmentsMod.INSTANT_VAMPIRE_EFFECT, 1, RandomUtil.nextInt(0, 3, random))) :
              add(new StatusEffectInstance(MoreEnchantmentsMod.VAMPIRE_EFFECT, RandomUtil.nextInt(4 * 20, 8 * 20, random), RandomUtil.nextInt(1, 4, random)))
          );
          add(new StatusEffectInstance(StatusEffects.WEAKNESS, RandomUtil.nextInt(15 * 20, 60 * 20, random), RandomUtil.nextInt(2, 4, random)));
          add(new StatusEffectInstance(StatusEffects.POISON, RandomUtil.nextInt(60 * 20, 200 * 20, random), RandomUtil.nextInt(3, 31, random)));
        }}
      ));
    }
  }

  @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/potion/PotionUtil;setPotion(Lnet/minecraft/item/ItemStack;Lnet/minecraft/potion/Potion;)Lnet/minecraft/item/ItemStack;"))
  private ItemStack setPotion(ItemStack stack, Potion potion) {
    if (!isStrengthened()) {
      return PotionUtil.setPotion(stack, potion);
    } else {
      return PotionUtil.setCustomPotionEffects(stack, new ArrayList<>(potion.getEffects()) {{
        add(new StatusEffectInstance(StatusEffects.REGENERATION, RandomUtil.nextInt(10 * 20, 50 * 20, random), RandomUtil.nextInt(1, 7, random)));
        add(new StatusEffectInstance(StatusEffects.RESISTANCE, RandomUtil.nextInt(20 * 20, 70 * 20, random), RandomUtil.nextInt(2, 5, random)));
      }});
    }
  }

  @Redirect(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getMaxUseTime()I"))
  private int getMaxUseTime(ItemStack stack) {
    if (isStrengthened()) return 5;
    else return stack.getMaxUseTime();
  }

}
